/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.snia.server.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.security.AuthenticationException;
import org.apache.cxf.interceptor.security.JAASLoginInterceptor;
import org.apache.cxf.message.Message;
import org.snia.cdmi.Headers;
import org.snia.cdmi.exception.UnauthorizedException;

public class RestSecurityInterceptor extends JAASLoginInterceptor {
	
    private static final Logger LOG = LogUtils.getL7dLogger(RestSecurityInterceptor.class);
    private String contextName;
    
    @Override
	public void setContextName(String name) {
        contextName = name;
    }
    
    @Override
	public String getContextName() {
        return contextName;
    }
    
	@Override
	public void handleMessage(Message message) throws Fault {        
        try {
        	//TODO 如何获得Header中的Headers.AUTHORIZATION
        	@SuppressWarnings("unchecked")
			HashMap<String, Object> headers = (HashMap<String, Object>) message.get(Message.PROTOCOL_HEADERS);
        	@SuppressWarnings("unchecked")
			List<String> auth_ls = (List<String>)headers.get(Headers.AUTHORIZATION);
        	@SuppressWarnings("unchecked")
			List<String> date_ls = (List<String>)headers.get(Headers.DATE);
        	
            String authorization = (auth_ls == null || auth_ls.size() == 0) ? null : auth_ls.get(0);
            String request_date = (date_ls == null || date_ls.size() == 0) ? null : date_ls.get(0);
            
            System.out.println("Headers.AUTHORIZATION: " + authorization);
            
            String http_method = (String) message.get(Message.HTTP_REQUEST_METHOD);
            String http_uri = (String) message.get(Message.REQUEST_URI);
            
            
            if(authorization == null || http_method == null || request_date == null || http_uri == null){
            	throw new AuthenticationException("客戶端沒有傳入檢驗參數");
            }
            
            String cfg_path = this.getClass().getResource("jaas.cfg").getPath();
            System.out.println("JAAS Config File Path: " + cfg_path);
        	System.setProperty("java.security.auth.login.config", "file:E:/TSpace/jtadf-cloud-router/test_src/com/alpha/cloud/test/jaas_sample");
        	List<String> signParams = new ArrayList<String>();
        	signParams.add(authorization);
        	signParams.add(http_method);
        	signParams.add(http_uri);
        	signParams.add(request_date);
            LoginContext ctx = new LoginContext("CSESigner", new My1CallbackHandler(signParams));
//            LoginContext ctx = new LoginContext(contextName, new My1CallbackHandler(signParams));
            
            
            ctx.login();
            
            headers = null;
            auth_ls = null;
//            Subject subject = ctx.getSubject();
            
//            message.put(SecurityContext.class, createSecurityContext(subject)); 
        } catch (LoginException ex) {
            String errorMessage = "Unauthorized : " + ex.getMessage();
            LOG.fine(errorMessage.toString());
//            throw new AuthenticationException(errorMessage);
            throw new UnauthorizedException(errorMessage);
        }
	}
	
//    @Override
//    protected CallbackHandler getCallbackHandler(final String name, final String password) {
//        return new NamePasswordCallbackHandler(name, password) {
//            protected boolean handleCallback(Callback c) {
//            	System.out.println("Cccxxxx:" + c.toString());
////                if (c instanceof ObjectCallback) {
////                    ((ObjectCallback)c).setObject(password);
////                    return true;
////                } else {
////                    return false;
////                }
//            	return false;
//            }
//        };
//    }   
}


/**
 * The application implements the CallbackHandler.
 * 
 * <p>
 * This application is text-based. Therefore it displays information to the user
 * using the OutputStreams System.out and System.err, and gathers input from the
 * user using the InputStream System.in.
 */
class My1CallbackHandler implements CallbackHandler {
	
	private String authorization;
	private String method;
	private String uri;
	private String date;

	
	public My1CallbackHandler(List<String> signParams){
		if(signParams == null || signParams.size() < 4){
			throw new IllegalArgumentException(
			"Parameter resourcePath is empty");
		}
		authorization = signParams.get(0);
		method = signParams.get(1);
		uri = signParams.get(2);
		date = signParams.get(3);
		System.out.println("\t\t[SecurityLoginModule] "
				+ "request entered authorization: " + this.authorization);
		System.out.println("\t\t[SecurityLoginModule] "
				+ "request entered method: " + this.method);
		System.out.println("\t\t[SecurityLoginModule] "
				+ "request entered uri: " + this.uri);
		System.out.println("\t\t[SecurityLoginModule] "
				+ "request entered date: " + this.date);	
		System.out.println();
	}
	
	@Override
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		
		int length = callbacks.length;
		TextInputCallback nc = null;
		
		if(length > 0)  nc = (TextInputCallback) callbacks[0];		
		nc.setText(authorization);
		if(length > 1 )	nc = (TextInputCallback) callbacks[1];
		nc.setText(method);
		if(length > 2 )	nc = (TextInputCallback) callbacks[2];
		nc.setText(uri);
		if(length > 3)  nc = (TextInputCallback) callbacks[3];
		nc.setText(date);
	}
}
